]> dgit.raspbian.org Git - gnome-shell.git/commitdiff
workspacesView: Add minimap on secondary monitors
authorFlorian Müllner <fmuellner@gnome.org>
Sat, 20 Feb 2021 10:18:29 +0000 (11:18 +0100)
committerMarge Bot <marge-bot@gnome.org>
Tue, 2 Mar 2021 21:56:30 +0000 (21:56 +0000)
The workspace minimap is much less prominent than the old workspace
switcher, and serves primarily as an indicator.

That means that duplicating it on secondary monitors (if workspaces
on non-primaries are enabled) is harder to mistake for per-monitor
workspaces, so make some people happy by including the minimap on
every monitor.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1735>

data/theme/gnome-shell-sass/widgets/_overview.scss
js/ui/workspacesView.js

index f952c52036b061c823445cf28287d882be68f519..6f0c501ed8268f0ff95c4b54a9162c23141671ba 100644 (file)
@@ -1,6 +1,6 @@
 /* OVERVIEW */
 
-.controls-manager {
+.controls-manager, .secondary-monitor-workspaces {
   spacing: 24px;
 }
 
index f9c7fcdccfdd268f22029237ffbe1686ecf51289..396dd700261ad7bc26662bc5ce8bf805a73d49c1 100644 (file)
@@ -9,6 +9,7 @@ const OverviewControls = imports.ui.overviewControls;
 const SwipeTracker = imports.ui.swipeTracker;
 const Util = imports.misc.util;
 const Workspace = imports.ui.workspace;
+const { ThumbnailsBox, MAX_THUMBNAIL_SCALE } = imports.ui.workspaceThumbnail;
 
 var WORKSPACE_SWITCH_TIME = 250;
 
@@ -604,6 +605,7 @@ class SecondaryMonitorDisplay extends St.Widget {
         this._overviewAdjustment = overviewAdjustment;
 
         super._init({
+            style_class: 'secondary-monitor-workspaces',
             constraints: new Layout.MonitorConstraint({
                 index: this._monitorIndex,
                 work_area: true,
@@ -612,13 +614,58 @@ class SecondaryMonitorDisplay extends St.Widget {
 
         this.connect('destroy', () => this._onDestroy());
 
+        this._thumbnails = new ThumbnailsBox(
+            this._scrollAdjustment, monitorIndex);
+        this.add_child(this._thumbnails);
+
+        this._thumbnails.connect('notify::should-show',
+            () => this._updateThumbnailVisibility());
+
+        this._stateChangedId = this._overviewAdjustment.connect('notify::value',
+            () => this._updateThumbnailParams());
+
         this._settings = new Gio.Settings({ schema_id: MUTTER_SCHEMA });
         this._settings.connect('changed::workspaces-only-on-primary',
-            () => this._updateWorkspacesView());
-        this._updateWorkspacesView();
+            () => this._workspacesOnPrimaryChanged());
+        this._workspacesOnPrimaryChanged();
+    }
+
+    _getThumbnailParamsForState(state) {
+        const { ControlsState } = OverviewControls;
+
+        let opacity, scale;
+        switch (state) {
+        case ControlsState.HIDDEN:
+        case ControlsState.WINDOW_PICKER:
+            opacity = 255;
+            scale = 1;
+            break;
+        case ControlsState.APP_GRID:
+            opacity = 0;
+            scale = 0.5;
+            break;
+        default:
+            opacity = 255;
+            scale = 1;
+            break;
+        }
+
+        return { opacity, scale };
     }
 
-    _getWorkspacesBoxForState(state, box, padding) {
+    _getThumbnailsHeight(box) {
+        if (!this._thumbnails.visible)
+            return 0;
+
+        const [width, height] = box.get_size();
+        const { expandFraction } = this._thumbnails;
+        const [thumbnailsHeight] = this._thumbnails.get_preferred_height(width);
+        return Math.min(
+            thumbnailsHeight * expandFraction,
+            height * MAX_THUMBNAIL_SCALE);
+    }
+
+    _getWorkspacesBoxForState(state, box, padding, thumbnailsHeight, spacing) {
         const { ControlsState } = OverviewControls;
         const workspaceBox = box.copy();
         const [width, height] = workspaceBox.get_size();
@@ -627,6 +674,11 @@ class SecondaryMonitorDisplay extends St.Widget {
         case ControlsState.HIDDEN:
             break;
         case ControlsState.WINDOW_PICKER:
+            workspaceBox.set_origin(0, padding + thumbnailsHeight + spacing);
+            workspaceBox.set_size(
+                width,
+                height - 2 * padding - thumbnailsHeight - spacing);
+            break;
         case ControlsState.APP_GRID:
             workspaceBox.set_origin(0, padding);
             workspaceBox.set_size(
@@ -643,16 +695,27 @@ class SecondaryMonitorDisplay extends St.Widget {
 
         const themeNode = this.get_theme_node();
         const contentBox = themeNode.get_content_box(box);
-        const [, height] = contentBox.get_size();
+        const [width, height] = contentBox.get_size();
+        const { expandFraction } = this._thumbnails;
+        const spacing = themeNode.get_length('spacing') * expandFraction;
         const padding =
             Math.round((1 - SECONDARY_WORKSPACE_SCALE) * height / 2);
 
+        const thumbnailsHeight = this._getThumbnailsHeight(contentBox);
+
+        if (this._thumbnails.visible) {
+            const childBox = new Clutter.ActorBox();
+            childBox.set_origin(0, padding);
+            childBox.set_size(width, thumbnailsHeight);
+            this._thumbnails.allocate(childBox);
+        }
+
         const {
             currentState, initialState, finalState, transitioning, progress,
         } = this._overviewAdjustment.getStateTransitionParams();
 
         let workspacesBox;
-        const workspaceParams = [contentBox, padding];
+        const workspaceParams = [contentBox, padding, thumbnailsHeight, spacing];
         if (!transitioning) {
             workspacesBox =
                 this._getWorkspacesBoxForState(currentState, ...workspaceParams);
@@ -670,6 +733,15 @@ class SecondaryMonitorDisplay extends St.Widget {
         if (this._settings)
             this._settings.run_dispose();
         this._settings = null;
+
+        if (this._stateChangedId)
+            this._overviewAdjustment.disconnect(this._stateChangedId);
+        this._stateChangedId = 0;
+    }
+
+    _workspacesOnPrimaryChanged() {
+        this._updateWorkspacesView();
+        this._updateThumbnailVisibility();
     }
 
     _updateWorkspacesView() {
@@ -691,6 +763,41 @@ class SecondaryMonitorDisplay extends St.Widget {
         this.add_child(this._workspacesView);
     }
 
+    _updateThumbnailVisibility() {
+        const visible =
+            this._thumbnails.should_show &&
+            !this._settings.get_boolean('workspaces-only-on-primary');
+
+        if (this._thumbnails.visible === visible)
+            return;
+
+        this._thumbnails.show();
+        this._thumbnails.ease_property('expand-fraction', visible ? 1 : 0, {
+            duration: OverviewControls.SIDE_CONTROLS_ANIMATION_TIME,
+            mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+            onComplete: () => (this._thumbnails.visible = visible),
+        });
+    }
+
+    _updateThumbnailParams() {
+        const { initialState, finalState, progress } =
+            this._overviewAdjustment.getStateTransitionParams();
+
+        const initialParams = this._getThumbnailParamsForState(initialState);
+        const finalParams = this._getThumbnailParamsForState(finalState);
+
+        const opacity =
+            Util.lerp(initialParams.opacity, finalParams.opacity, progress);
+        const scale =
+            Util.lerp(initialParams.scale, finalParams.scale, progress);
+
+        this._thumbnails.set({
+            opacity,
+            scale_x: scale,
+            scale_y: scale,
+        });
+    }
+
     getActiveWorkspace() {
         return this._workspacesView.getActiveWorkspace();
     }